package com.zhn.evsi.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhn.evsi.client.AllianceClient;
import com.zhn.evsi.client.CharacterClient;
import com.zhn.evsi.client.CharacterPublicClient;
import com.zhn.evsi.client.CorporationClient;
import com.zhn.evsi.common.RedisCache;
import com.zhn.evsi.domain.dto.System.SysUserDTO;
import com.zhn.evsi.domain.dto.System.SysUserInfoEditDTO;
import com.zhn.evsi.domain.dto.evsi.alliance.EvsiAllianceInfoDTO;
import com.zhn.evsi.domain.dto.evsi.character.EvsiCharacterBloodlineDTO;
import com.zhn.evsi.domain.dto.evsi.character.EvsiCharacterPublicInfoDTO;
import com.zhn.evsi.domain.dto.evsi.common.EvsiIconDTO;
import com.zhn.evsi.domain.dto.evsi.corporation.EvsiCorporationPublicInfoDTO;
import com.zhn.evsi.domain.entity.System.SysFile;
import com.zhn.evsi.domain.entity.System.SysMail;
import com.zhn.evsi.domain.entity.System.SysUser;
import com.zhn.evsi.domain.entity.evsi.EvsiAuthToken;
import com.zhn.evsi.exception.CustomException;
import com.zhn.evsi.mapper.EvsiCharacterMapper;
import com.zhn.evsi.mapper.SysUserMapper;
import com.zhn.evsi.service.IEvsiAuthTokenService;
import com.zhn.evsi.service.ISysFileService;
import com.zhn.evsi.service.ISysUserService;
import com.zhn.evsi.utils.MailUtil;
import com.zhn.evsi.utils.OSSUtil;
import com.zhn.evsi.utils.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Resource
    private OSSUtil ossUtil;

    @Autowired
    private CharacterPublicClient characterPublicClient;
    @Autowired
    private AllianceClient allianceClient;

    @Autowired
    private CorporationClient corporationClient;

    @Autowired
    private EvsiCharacterMapper characterMapper;

    @Resource
    private MailUtil mailUtil;

    @Autowired
    private ISysFileService fileService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IEvsiAuthTokenService authTokenService;


    /**
     * 验证当前邮箱是否存在，如果存在，则返回，不存在，则存储，然后发送验证码邮件
     */
    @Override
    public void register(SysUserDTO sysUserDTO) {
        // 验证邮箱是否存在
        if (this.count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, sysUserDTO.getUsername())) > 0) {
            throw new CustomException("当前邮箱已存在，请登录");
        }
        // 发送邮件
        String randomCode = RandomUtil.randomString(6); // 自动生成六位验证码
        // 首先将验证码存入redis中(20min)
        sysUserDTO.setCode(randomCode);
        redisCache.setCacheObject("User:Character:SignCode:" + sysUserDTO.getUsername(), sysUserDTO, 20, TimeUnit.MINUTES);
        try {
            mailUtil.sendMail(SysMail.builder()
                    .receiveEmail(sysUserDTO.getUsername())
                    .subject("Evsi注册验证码")
                    .content(randomCode)
                    .build());
        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 验证邮箱发送的验证码是否正确
     */
    @Override
    public void codeActivation(SysUserDTO sysUserDTO) {
        SysUserDTO userDTO = redisCache.getCacheObject("User:Character:SignCode:" + sysUserDTO.getUsername());
        if (userDTO.getCode() == null) {
            throw new CustomException("验证码超时！");
        }
        if (sysUserDTO.getCode().equals(userDTO.getCode())) {
            SysUser sysUser = new SysUser();
            BeanUtil.copyProperties(userDTO, sysUser);
            sysUser.setEmail(sysUser.getEmail());
            if (this.save(sysUser)) {
                // 保存后删除redis中的数据
                redisCache.deleteObject("User:Character:SignCode:" + sysUserDTO.getUsername());
            }
        }
    }


    /**
     * 上传用户头像
     */
    @Override
    public String uploadAvatar(MultipartFile file, Integer state) {

        if (state == null) {
            state = 0;
        }

        String fileMd5 = null;
        try {
            InputStream inputStream = file.getInputStream();
            fileMd5 = DigestUtil.md5Hex(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        SysFile sysFile = fileService.getOne(new LambdaQueryWrapper<SysFile>().eq(SysFile::getFileMd5, fileMd5).eq(SysFile::getState, state));

        // TODO SecurityUtil.getUsername;
        String username = "1085155177@qq.com";

        if (ObjectUtil.isNull(sysFile)) {
            String avatar = ossUtil.OSSUpload(file, "avatar", state, username);

            this.update(new LambdaUpdateWrapper<SysUser>().set(SysUser::getAvatar, avatar).eq(SysUser::getUsername, username));
            return avatar;
        }else {
            this.update(new LambdaUpdateWrapper<SysUser>().set(SysUser::getAvatar, sysFile.getFilePath()).eq(SysUser::getUsername, username));
            return sysFile.getFilePath();
        }
    }

    /**
     * 登录
     * */
    @Override
    public void login(SysUserDTO sysUserDTO) {
        // 判断是否为空
        if (sysUserDTO == null || ObjectUtil.isNull(sysUserDTO.getUsername()) || sysUserDTO.getPassword() == null) {
            throw new CustomException("账号或密码不存在!");
        }

        // TODO jwt登录生成token

        // 登录成功后获取用户信息,然后将
        EvsiCharacterPublicInfoDTO characterPublicInfoDTO = redisCache.getCacheObject("User:Character:Main:" + sysUserDTO.getUsername());
        if (characterPublicInfoDTO == null) {
            SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, sysUserDTO.getUsername()));
            // 查询当前主角色的详细信息
            characterPublicInfoDTO = characterPublicClient.publicInfo(user.getCharacterMain());
            characterPublicInfoDTO.setCharacters(user.getCharacterMain());

        }
        redisCache.setCacheObject("User:Character:Main:" + sysUserDTO.getUsername(), characterPublicInfoDTO, 2, TimeUnit.HOURS);

        // 返回菜单 用户信息（不包含账号密码） 所有绑定的角色”id“以及角色信息
    }

    /**
     * 角色切换
     *
     * @param characterId - 角色id
     *
     * 登录的时候将主角色与用户账号绑定一起存入redis中,
     * 切换的时候将切换的角色与用户账号重新绑定
     * 需要查询什么角色就从redis中获取角色id
     * 注意 : 登录绑定,退出网页或退出则 前端消除所有缓存, 后端重新赋给时间20min
     * */
    @Override
    public void handoff(Integer characterId) {
        // 获取用户username
        String username = "1085155177@qq.com";

        // 通过id获取角色id
        Integer characters = authTokenService.getOne(new LambdaQueryWrapper<EvsiAuthToken>().eq(EvsiAuthToken::getId, characterId)).getCharacterID();
        EvsiCharacterPublicInfoDTO evsiCharacterPublicInfoDTO = characterPublicClient.publicInfo(characters);
        EvsiAllianceInfoDTO evsiAllianceInfoDTO = allianceClient.alliancesInfo(evsiCharacterPublicInfoDTO.getAlliance_id());

        EvsiIconDTO allianceIconIconDTO = allianceClient.allianceIcon(evsiCharacterPublicInfoDTO.getAlliance_id());
        EvsiCorporationPublicInfoDTO corporations = corporationClient.corporations(evsiCharacterPublicInfoDTO.getCorporation_id());
        EvsiIconDTO cropIconDTO = corporationClient.corporationIcon(evsiCharacterPublicInfoDTO.getCorporation_id());

        evsiCharacterPublicInfoDTO.setCharacters(characters);
        evsiCharacterPublicInfoDTO.setAlliance_name(evsiAllianceInfoDTO.getName());
        evsiCharacterPublicInfoDTO.setAlliance_icon(allianceIconIconDTO.getPx64x64());
        evsiCharacterPublicInfoDTO.setCorporation_name(corporations.getName());
        evsiCharacterPublicInfoDTO.setCorporation_icon(cropIconDTO.getPx64x64());
        EvsiCharacterBloodlineDTO bloodline = characterMapper.bloodline(evsiCharacterPublicInfoDTO.getBloodline_id());
        evsiCharacterPublicInfoDTO.setBloodline_name(bloodline.getBloodlineName() + "/" + bloodline.getRaceName());
        if (Objects.equals(evsiCharacterPublicInfoDTO.getError(), "Character not found")) {
            throw new CustomException("当前角色id不存在");
        }
        evsiCharacterPublicInfoDTO.setCharacters(characters);
        redisCache.setCacheObject("User:Character:Main:" + username, evsiCharacterPublicInfoDTO, 2, TimeUnit.HOURS);
    }

    /**
     * 退出账号或关闭网站
     * */
    @Override
    public void logout(Integer characterId) {

        // TODO SecurityUtil.getUsername 获取用户username
        String username = "1085155177@qq.com";

        // 根绝角色ID获取角色id
        Integer characters = authTokenService.getOne(new LambdaQueryWrapper<EvsiAuthToken>().eq(EvsiAuthToken::getId, characterId)).getCharacterID();
        EvsiCharacterPublicInfoDTO characterPublicInfoDTO = characterPublicClient.publicInfo(characters);
        characterPublicInfoDTO.setCharacters(characters);
        redisCache.setCacheObject("User:Character:Main:" + username, characterPublicInfoDTO, 20, TimeUnit.MINUTES); // 预留20min人性化处理,防止重复筛选角色

    }

    /**
     * 修改用户信息
     *
     * @param sysUserInfoEditDTO - 用户信息
     * */
    @Override
    @Transactional
    public Boolean editUserInfo(SysUserInfoEditDTO sysUserInfoEditDTO) {


        // SecurityUtil.getUsername 获取用户信息
        String username = "1085155177@qq.com";
        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(sysUserInfoEditDTO, sysUser);
        sysUser.setUpdateBy(username);
        sysUser.setUpdateTime(new Date());
        return this.update(sysUser, new LambdaUpdateWrapper<SysUser>().eq(SysUser::getUsername, username));
    }
}
